Cosmograph
Cosmograph
is a powerful and flexible visualization component built on top of the
@cosmograph/cosmos
GPU-accelerated force graph
layout algorithm and rendering engine. With its extensive configuration options and seamless integration
with other components, Cosmograph
is an essential tool for building graph data-driven applications.
Creating a Cosmograph instance
- React
- JS/TS
- Data
import { Cosmograph, CosmographProvider } from '@cosmograph/react'
export const Component = ({ nodes, links}) => {
return (
<Cosmograph nodes={nodes} links={links} />
)
}
import { Cosmograph } from '@cosmograph/cosmograph'
import { nodes, links } from './path/to/data'
// Create an HTML element
const div = document.createElement('div')
document.body.appendChild(div)
// Create a Cosmograph instance with this element
const cosmograph = new Cosmograph(div)
// Set the data for the Cosmograph instance
cosmograph.setData(nodes, links)
export const nodes = [
{ id: 'node1' },
{ id: 'node2' },
{ id: 'node3' },
]
export const links = [
{ source: 'node1', target: 'node2' },
{ source: 'node2', target: 'node3' },
]
Passing the data and configuration
If you use React, the data and configuration can be passed as props to the Cosmograph
component. React will
take care of updating the graph when the data or configuration changes. If you use JavaScript, you can pass
the data and configuration to the Cosmograph
instance using the setData
and setConfig
methods.
- React
- JS/TS
<Cosmograph nodes={nodes} links={links} nodeColor={d => d.color} nodeSize={20} linkWidth={2} />
const config = {
nodeColor: d => d.color,
nodeSize: 20,
linkWidth: 2,
}
cosmograph.setConfig(config)
cosmograph.setData(nodes, links)
You can load only nodes without any links into Cosmograph
. In this case, Cosmograph
will automatically configure itself to render the nodes as embeddings, without running a simulation.
If you want to simulate a network with links between nodes, check the Simulation setttings section.
Rendering preferences
Node appearance
The appearance of the nodes in the Cosmograph
can be customized using various configuration properties. Here is a list of general properties that control the node appearance:
nodeColor
allows you to define the color of the nodes. It can be either a function that determines the color dynamically based on the node properties, or just a color string that can be specified in any popular color format such as Hex or in RGBA format[number, number, number, number]
. The default value is#b3b3b3
.nodeSize
allows you to set the size of the nodes. Similar tonodeColor
, it can be a function that determines the size dynamically based on the node properties, or a fixed value in pixels. The default value is4
.nodeSizeScale
is a scale factor that can be used to adjust the node size. It is useful when you want to implement a node scale slider. The default value is1
.scaleNodesOnZoom
property is a boolean that determines whether the nodes should be scaled when zooming in or out. By default, it is set totrue
.
Node appearance configuration example
Here is a code example that demonstrates how to customize the size and color of the nodes:
- React
- JS/TS
<Cosmograph
...
nodeSize={(n, i) => n.size}
nodeColor={(n, i) => n.color}
/>
const config = {
nodeSize: (n, i) => n.size,
nodeColor: (n, i) => n.color,
}
cosmograph.setConfig(config)
In this example, the nodeSize
property is set to a function that accesses the size
property for each node, and the nodeColor
property is also set to a function that accesses the color
property of the node.
Node states
Node can be selected, focused or hovered. Each state has its own set of properties.
Selected state is achieved when selectNode()
, selectNodes()
, or selectNodesInRange()
is performed on a node. Multiple nodes can be in the selected state.
nodeGreyoutOpacity
defines the opacity of the unselected nodes when a selection is active. It visually distinguishes the selected nodes from the rest. The default value is0.1
.
Focused state is set using focusNode()
. When a node is focused, a focus ring is rendered around it. Only one node can be in the focused state at a time.
focusedNodeRingColor
sets the color of the focus ring. The default color iswhite
.
Hovered state occurs when the mouse hovers over a node. When a node is hovered, a hover ring is rendered around it. Only one node can be in the highlighted state.
renderHoveredNodeRing
property is a boolean that enables or disables the node hovered state logic on hover. By default, it is set totrue
.hoveredNodeRingColor
sets the color of the hover ring. The default color iswhite
.
Hovered node has an individual label and there is a special onNodeMouseOver
callback for hovered node.
Hovered and focused are different states that render a relevant ring around node. Both hoveredNodeRingColor
and focusedNodeRingColor
can be specified in a Hex or common color name like red
.
Example showing difference between hovered and focused nodes
- React
- JS/TS
import React, { useRef, useEffect } from 'react'
import { Cosmograph } from '@cosmograph/react'
export function Example ({ nodes, links }) {
// Create a ref to hold the Cosmograph instance
const cosmographRef = useCallback((ref) => {
// Focus node after Cosmograph mount
ref?.focusNode({ id: 'node0' })
}, [])
return (<>
<Cosmograph
ref={cosmographRef}
hoveredNodeRingColor={'red'}
focusedNodeRingColor={'yellow'}
... />
</>)
}
const config = {
hoveredNodeRingColor:'red',
focusedNodeRingColor: 'yellow',
}
...
cosmograph.setConfig(config)
cosmograph.focusNode(({ id: 'node0' }))
Node labels
Node labels are used to display text for each node in a visualization. By default, the id
property of a node is used as the label text. However, you can customize the label text for each node using the nodeLabelAccessor
property.
nodeLabelAccessor
takes a function that accepts a node object as input and returns a string. You can use this function to generate custom label text based on the properties or other data associated with each node. DefaultnodeLabelAccessor
functionn => n.id
uses theid
property of the node as the label text. However, you can provide your own function withstring
as result to generate the desired label text for each node.
Label types and controlling them
There are few types of labels: dynamic, top, hovered and custom. They represent individual groups and does not intersect.
Dynamic labels appear for the currently visible nodes on the screen while zooming in and hide while zooming out. They help quickly identify nodes at different levels of zoom.
showDynamicLabels
used to control whether or not dynamic labels are displayed. The default value istrue
.
Top labels are labels for the nodes with the highest number of connections by default. Alternatively, if showTopLabelsValueKey
is specified, top labels will be shown for the nodes with the highest values of this key.
showTopLabelsValueKey
represents astring
key of a node property to calculate the top nodes by. The default value isundefined
.showTopLabelsLimit
property sets the maximum number of top nodes to show labels for, with a default value of100
.showTopLabels
is a boolean that turns the top node labels on or off. The default value isfalse
.
Hovered label is a single label that displays for the currently hovered node.
showHoveredNodeLabel
property is a boolean that turns the label for the hovered node on or off. The default value istrue
.
Specific labels
You can display labels for specific nodes by providing an array of nodes to the showLabelsFor
property. These labels will always be visible for the listed nodes. You can provide the entire nodes as well as objects with only their ids. By default, this array is empty, meaning no custom labels will be shown.
Here's an example of how to use the showLabelsFor
property to show specific labels only by node ids:
- React
- JS/TS
- Data
<Cosmograph
...
showDynamicLabels={false}
showLabelsFor={[{ id: "node0" }, { id: "node3" }]}
/>
const config = {
showDynamicLabels: false,
showLabelsFor: [{ id: "node0" }, { id: "node3" }]
}
cosmograph.setConfig(config)
export const nodes = [
{ id: 'node0', value: 1 },
{ id: 'node1', value: 2 },
{ id: 'node2', value: 3 },
{ id: 'node3', value: 4 },
{ id: 'node4', value: 5 },
]
To turn off labels completely, you will need to set showDynamicLabels
, showTopLabels
, and showHoveredNodeLabel
to false
, and ensure that showLabelsFor
is empty.
Labels style
To style node labels using CSS, you can use the following properties:
nodeLabelClassName
specifies the CSS class to apply to the labels. It can be set to astring
or a function that returns astring
representing the CSS class to use for the labels. The default value isundefined
.hoveredNodeLabelClassName
property specifies the CSS class to apply for the hovered node label same way as fornodeLabelClassName
. The default value isundefined
.nodeLabelColor
can be set to astring
or a function that returns astring
representing the color to use for the label in a CSS-acceptable color format. The default value isundefined
.hoveredNodeLabelColor
property work in the same way, but apply to the label when the node is hovered over. The default value isundefined
.
By utilizing these properties, you can style the labels of nodes in various ways, allowing you to differentiate them from other elements within the graph.
Link customization
The look of links in the Cosmograph
can be customized using the following properties:
renderLinks
is a boolean that determines whether to render the links. The default value istrue
.linkColor
allows you to define the color of the links. It can be either a function that determines the color dynamically based on the link properties, or just a color string that can be specified in any popular color format such as Hex or in RGBA format[number, number, number, number]
. The default value is#666666
.linkWidth
is a function that returns anumber
or a single numerical value in pixels that determines the width of the links. The default value is1
.linkWidthScale
is a scale factor for the link width. The final link width calculated by multiplying thelinkWidth
value by thelinkWidthScale
. The default value is1
.linkArrows
property is a boolean that controls whether arrows are displayed at the ends of the links. By default, this property is set totrue
.linkArrowsSizeScale
is a scale factor for the size of the link arrows. The default value is1
.linkGreyoutOpacity
is responsible for opacity of the links when the selection is active. It can be specified from0
to1
, with a default value of0.1
.linkVisibilityDistance
defines the minimum and maximum of link lengths in pixels. Links shorter than the minimum length will be fully opaque. Links longer than the maximum length will have a minimum transparency set bylinkVisibilityMinTransparency
. For links between those two length values, the transparency will be interpolated between fully opaque and the minimum transparency. So as you zoom in and out, links will become more or less transparent depending on their length. This helps focus on local connections over long range connections by making long links more transparent. The default range is[50, 150]
.linkVisibilityMinTransparency
is a transparency value that the link will have when its length reaches the maximum link distance value fromlinkVisibilityDistanceRange
, The default is0.25
, meaning the longest links will have 25% transparency.
Curved links
Curved links enhance graph aesthetic appeal but can potentially impact performance due to the additional computational complexity involved in rendering them.
curvedLinks
is a boolean that determines whether to render curved links. The default value isfalse
.curvedLinkSegments
is a number of segments in a curved line. More segments can result in slower rendering performance. Default is19
.curvedLinkWeight
affects the shape of the curve. Higher values will create more curved links, while lower values will be more straight. Default is0.8
.curvedLinkControlPointDistance
defines the position of the control point of the curve on the normal from the center of the line. If set to 1, the control point is at a distance equal to the length of the line. Default is0.5
.
Link appearance configuration example
- React
- JS/TS
const colors = ['#88C6FF', '#FF99D2', '#2748A4'];
<Cosmograph
linkWidth={() => 1 + 2 * Math.random()}
linkColor={() => colors[Math.floor(Math.random() * colors.length)]}
...
/>
const colors = ['#88C6FF', '#FF99D2', '#2748A4'];
const config = {
linkWidth: () => 1 + 2 * Math.random(),
linkColor: () => colors[Math.floor(Math.random() * colors.length)]
}
cosmograph.setConfig(config)
Tweaking zoom
initialZoomLevel
sets the customnumber
for initial zoom level. This property can be helpful if the graph appears too small and needs to be scaled up for better visibility. Default:1
.disableZoom
boolean disables zoom and drag events, preventing users from zooming in or out and dragging the graph canvas. This can be useful in scenarios where zooming and dragging functionality is not desired. Default:false
.
Fitting view
These properties have effect only during initialization. You can check methods to fit viewport after initialization here.
fitViewOnInit
determines whether to center and zoom the view to fit all nodes in the scene on initialization. The default value istrue
.fitViewDelay
specifies a delay in milliseconds before fitting the view. It is useful if you want the layout to stabilize a bit before fitting the view. The default value is250
.fitViewByNodesInRect
is used whenfitViewOnInit
is set totrue
. It defines the corner coordinates[[left, bottom], [right, top]]
of the rectangle that encloses the nodes in the scene. The default value isundefined
.
Miscellaneous
backgroundColor
sets the canvas background color. The default value is#222222
.showFPSMonitor
shows or hides the WebGL performance monitor. The default value isfalse
.pixelRatio
property sets the canvas pixel ratio. A higher value forpixelRatio
results in sharper graph elements. However, setting a value higher than the target device's pixel ratio may not have any effect. It's important to note that setting a higherpixelRatio
can impact performance on certain machines. The default value forpixelRatio
is2
.nodeSamplingDistance
specifies the minimum distance in pixels between sampled nodes when calling thegetSampledNodePositionsMap()
method. It controls the density of the node sampling - larger values will result in fewer nodes being included in the sample. The default value is150
pixels.
Simulation settings
Cosmograph
detects if a graph only contains nodes without links. In this case, it will automatically disable the simulation, since running a force simulation would have no effect without links between nodes. However, if links are present in the graph data, Cosmograph
will enable the simulation by default to position the nodes based on the links and forces.
This automatic behavior of enabling or disabling the simulation can be overridden through configuration if desired.
Disabling simulaiton
The disableSimulation
property can be tweaked during initial configuration. This means any changes will take effect until data is set.
The disableSimulation
property controls whether Cosmograph
runs a force layout simulation or acts as just a renderer for pre-computed embeddings.
disableSimulation
can be set to true
, false
, or null
. When disableSimulation
is true
, the simulation is disabled and Cosmograph
just renders the graph. Node positions are determined by the x
and y
values in the data. If x
and y
are not specified, random positions are assigned.
If set to null
, Cosmograph will check for links when data is first loaded. If links exist, it sets disableSimulation
to false
to enable simulation. If no links exist, it sets disableSimulation
to true
to disable simulation.
Default value for disableSimulation
is null
.
Initialization parameters
This properties is applied only during the initialization of the Cosmograph
.
spaceSize
defines the size of the simulation space. The maximum value is8192
, limited by the end user's GPU specifications. Increasing the space size allows nodes more room to move around. The default value is4096
.randomSeed
controls the randomness of the layout across different simulation runs. It can benumber
orstring
. Default:undefined
.
Forces
Tweaking simulation forces allow to customize and fine-tune the behavior of the forces within the system, enabling them to create dynamic and interactive simulations of nodes interaction.
Name | Description | Recommended range | Default |
---|---|---|---|
simulationRepulsion | Controls the repulsion force coefficient, determining the strength of node repulsion. Increase for stronger repulsion, decrease for weaker repulsion. | 0.0 -2.0 | 0.1 |
simulationRepulsionTheta | Controls the level of detail in Many-Body force calculations. When useQuadtree is enabled, it corresponds to the Barnes-Hut approximation criterion. Higher values provide more accurate calculations, while lower values give faster but less precise results. | 0.3 -2.0 | 1.7 |
simulationLinkSpring | Adjusts the link spring force coefficient, determining the strength of attraction between connected nodes. Increase for stronger attraction, decrease for weaker attraction. | 0.0 -2.0 | 1.0 |
simulationLinkDistance | Defines the minimum distance between linked nodes, affecting their positioning. Increase for more spacing, decrease for closer proximity. | 1 -20 | 2 |
simulationGravity | Adjusts the gravity force coefficient, determining how much nodes are attracted towards the center of the graph. Increase for stronger gravitational pull towards the center, decrease for weaker attraction. | 0.0 -1.0 | 0.0 |
simulationCenter | Changes the centering force coefficient, pulling nodes towards the center of the graph. Increase for more centered nodes, decrease for less centralization. | 0.0 -1.0 | 0.0 |
simulationFriction | Controls the friction coefficient, affecting how much nodes slow down over time. Higher values result in slower movement and longer simulation time, lower values allow faster movement and quicker convergence. | 0.8 -1.0 | 0.85 |
simulationDecay | Controls the force simulation decay coefficient. Higher values make the simulation "cool down" slower. Increase for a longer-lasting simulation, decrease for a faster decay. | 100 -10000 | 1000 |
simulationRepulsionFromMouse | Sets the repulsion force coefficient from the mouse cursor. Activates the repulsion force when the right mouse button is pressed. Increase for stronger repulsion from the cursor click, decrease for weaker repulsion. | 0.0 -5.0 | 2.0 |
- React
- JS/TS
<Cosmograph
...
simulationFriction={0.1}
simulationLinkSpring={0.5}
simulationLinkDistance={2.0}
/>
const config = {
simulationFriction: 0.1,
simulationLinkSpring: 0.5,
simulationLinkDistance: 2.0,
}
cosmograph.setConfig(config)
Quadtree algorithm
The experimental quadtree settings in the Cosmograph
library enable the use of the classic quadtree algorithm for the Many-Body force. This algorithm helps optimize the calculations involved in the force simulation.
-
useQuadtree
: When set totrue
, this property activates the quadtree algorithm for the Many-Body force. It is applied during the initialization of theCosmograph
component. The default value isfalse
. -
repulsionQuadtreeLevels
: This property defines the depth of the Barnes-Hut approximation used by the quadtree algorithm. It can only be used whenuseQuadtree
is set totrue
. Adjusting this value allows you to balance between accuracy and performance in the force simulation. Higher values provide more accurate results at the cost of longer computation time, while lower values offer faster but less precise simulations. The recommended range for this property is between 5 to 12, with a default value of12
.
useQuadtree
limitationsuseQuadtree
might not work on certain GPUs (e.g., Nvidia) and on Windows, unless ANGLE is disabled in the browser settings.
Events configuration
Cosmograph
supports several event handlers allowing you to react to user interactions with the graph. Try clicking on a node in the example below:
Mouse and zoom events
onClick(clickedNode?: N, index?: number, nodePosition?: [number, number], event: MouseEvent)
Triggered on every canvas click. If clicked on a node, its data will be passed as the first argument, index as the second argument, position as the third argument and the corresponding mouse event as the forth argument.
onLabelClick(node: N, event: MouseEvent)
Called when clicked on a label. The node data for this label will be passed as the first argument, and the corresponding mouse event as the second argument.
onMouseMove(hoveredNode?: N, index?: number, nodePosition?: [number, number], event: MouseEvent) => void
Called when mouse movement occurs. If the mouse hovers over a node, it receives the hovered node's data, index, position, and the corresponding mouse event as arguments.
onNodeMouseOver(hoveredNode: N, index: number, nodePosition: [number, number], event?: MouseEvent | D3ZoomEvent<HTMLCanvasElement, undefined>
Invoked when a node becomes highlighted, i.e. appears under the mouse as a result of a mouse event, zooming and panning, or movement of nodes. It receives the node's data, index, position, and the corresponding mouse event or D3 zoom event as arguments.
onNodeMouseOut(event?: MouseEvent | D3ZoomEvent<HTMLCanvasElement, undefined>)
Called when node is no longer underneath the mouse pointer because of a mouse event, zoom/pan event, or movement of nodes. The corresponding mouse event or D3 zoom event event will be passed as the first argument.
onZoomStart(event: D3ZoomEvent<HTMLCanvasElement, undefined>, userDriven: boolean)
Triggered when zooming or panning starts. It receives a D3 zoom event as the first argument and a boolean indicating whether the event was initiated by a user interaction.
onZoom(event: D3ZoomEvent<HTMLCanvasElement, undefined>, userDriven: boolean)
This callback function is continuously called during zooming or panning. It receives a D3 zoom event as the first argument and a boolean indicating whether the event was initiated by a user interaction.
onZoomEnd(event: D3ZoomEvent<HTMLCanvasElement, undefined>, userDriven: boolean)
Called when zooming or panning ends. It receives a D3 zoom event as the first argument and a boolean indicating whether the event was initiated by a user interaction.
Simulation callbacks
Cosmograph
also supports several callbacks that allow you to react to simulation events:
onSimulationStart()
This callback function is triggered when the simulation starts
onSimulationTick(alpha: number, hoveredNode?: N, index?: number, nodePosition?: [number, number])
Callback function that will be called on every simulation tick. The value of the argument alpha
will decrease over time as the simulation "cools down". If there's a node under the mouse pointer, its datum will be passed as the second argument, index as the third argument and position as the forth argument.
onSimulationEnd()
Triggered when the simulation stops.
onSimulationPause()
Triggered when the simulation pauses.
onSimulationRestart()
Callback function that will be called when the simulation is restarted.
onSetData(nodes: N[], links: L[])
This callback function executes when the data of the simulation is updated. It receives two parameters: an array of nodes
and an array of links
. Utilize this callback to respond to changes in the data and update the visualization accordingly.
Crossfilter callbacks
Cosomgraph has a built-in crossfilters that filters nodes and links arrays based on various selections such as Histogram
, Timeline
, Search
or manual nodes or links selection through clicking or using the API like selectNodes
.
Cosmograph supports two callbacks that enable you to monitor changes in crossfilters:
onNodesFiltered(filteredNodes?: N[])
Triggered whenever the nodes array is filtered using node-based crossfilter.
onLinksFiltered(filteredLinks?: L[])
Triggered whenever the links array is filtered using link-based crossfilter.
Controlling the graph
Cosmograph
provides methods to control your graph. In JavaScript or TypeScript, you can call these methods directly on the Cosmograph
instance. In React, you can access the Cosmograph
instance using the useCallback
or useRef
hook. Here's an example of methods usage:
- React
- JS/TS
import React, { useRef, useEffect } from 'react'
import { Cosmograph } from '@cosmograph/react'
export function GraphVisualization ({ nodes, links }) {
// Create a ref to hold the Cosmograph instance
const cosmographRef = useRef(null)
const zoomToNode = () => cosmographRef.current?.zoomToNode({{ id: 'node0' }})
return (<>
<button onClick={zoomToNode}>Zoom to "node0"</button>
<Cosmograph ref={cosmographRef} nodes={nodes} links={links} ... />
</>)
}
// In JavaScript you can simply call the methods on the Cosmograph
// instance once the graph has been initialized
cosmograph.zoomToNode({ id: 'node0' })
Node methods
selectNode(node: N, selectAdjacentNodes: boolean)
Selects a specific node. An optional boolean flag selectAdjacentNodes
that is false by default can be provided to select the adjacent nodes as well.
selectNodes(nodes: N[])
Selects a set of nodes by passing an array of nodes as an argument.
selectNodesInRange(selection: [[number, number], [number, number]] | null)
Selects the nodes within a specific range. The range can be specified as a two-dimensional array of boundaries or as null
to unselect all nodes.
getSelectedNodes()
Returns an array of nodes that are currently selected.
unselectNodes()
Clears the selection and unselects all nodes.
focusNode(node?: N)
Sets focus to a specific node by drawing a circle around it. If no node is provided, the focus is reset.
getAdjacentNodes(id: string)
Returns an array of adjacent nodes to a specific node by its id
, or undefined
.
getNodePositions()
Get current X and Y coordinates of all nodes. Returns an object where keys are the ids of the nodes and values are corresponding { x: number; y: number }
objects.
getNodePositionsMap()
Get current X and Y coordinates of all nodes. Returns a Map object where keys are the ids of the nodes and values are their corresponding X and Y coordinates in the [number, number] format.
getNodePositionsArray()
Get current X and Y coordinates of all nodes. Returns an array of [x: number, y: number]
arrays.